﻿using RabbitMQ.Client;

namespace Leo.Common.RabbitMQ
{
    /// <summary>
    /// 消息重试策略
    /// </summary>
    public class MessageRetryStrategy
    {

        private readonly string _destination;

        public bool Temporary { get; set; }
        internal RabbitQueueInfo RelatedQueue { get; }
        public TimeSpan RetryInterval { get; set; }
        public int RetryTimes { get; set; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="retryInterval">重试间隔</param>
        /// <param name="retryTimes">重试次数</param>
        /// <param name="queue">队列信息</param>
        /// <param name="temporary">临时状态</param>
        /// <param name="destination">目的地</param>
        public MessageRetryStrategy(TimeSpan retryInterval, int retryTimes, RabbitQueueInfo queue, bool temporary, string destination = null)
        {
            this.RetryInterval = retryInterval;
            this.RetryTimes = retryTimes;
            this.RelatedQueue = queue;
            this.Temporary = temporary;
            this._destination = destination;
        }


        internal RabbitExchangeInfo OrignalExchange
        {
            get
            {
                return this.RelatedQueue.PreferBinder.Exchange;
            }
        }

        public string Destination
        {
            get
            {
                return EnsureRetryDestination(this.RelatedQueue, this._destination);
            }
        }

        /// <summary>
        /// 确认 重试 目的地
        /// </summary>
        /// <param name="queue">队列</param>
        /// <param name="destination">目的地</param>
        /// <returns></returns>
        private static string EnsureRetryDestination(RabbitQueueInfo queue, string destination)
        {
            if (!string.IsNullOrWhiteSpace(destination))
            {
                return destination;
            }
            RabbitQueueBinder rabbitQueueBinder = queue.Binders.FirstOrDefault<RabbitQueueBinder>();
            if (rabbitQueueBinder == null)
            {
                return null;
            }
            return rabbitQueueBinder.GetRetryDestination();
        }

        /// <summary>
        /// 获取 重试 交换机
        /// </summary>
        /// <param name="retryRoutingKey"></param>
        /// <returns></returns>
        internal RabbitExchangeInfo GetRetryExchange(out string retryRoutingKey)
        {
            PublicationAddress publicationAddress = PublicationAddress.Parse(this.Destination);

            retryRoutingKey = publicationAddress.RoutingKey;

            ExchangeWorkMode exchangeType = Enum.Parse<ExchangeWorkMode>(publicationAddress.ExchangeType, true);

            RabbitExchangeInfo rabbitExchangeInfo = new RabbitExchangeInfo(publicationAddress.ExchangeName, exchangeType);

            rabbitExchangeInfo.redeclared = (this.OrignalExchange.redeclared || this.RelatedQueue.redeclared);

            if (this.Temporary)
            {
                rabbitExchangeInfo.AutoDelete = true;
                rabbitExchangeInfo.Durable = false;
            }
            return rabbitExchangeInfo;
        }


    }
}
